#include "i2c.h"

void I2C_initController(uint32_t base, uint32_t sysclkHz, uint32_t bitRate)
{ }

//*****************************************************************************
//
// I2C_enableInterrupt
//
//*****************************************************************************
void I2C_enableInterrupt(uint32_t base, uint32_t intFlags)
{
    //
    // Check the arguments.
    //
    ASSERT(I2C_isBaseValid(base));

    //
    // Enable the desired basic interrupts
    //
    HWREG(base + I2C_O_INTR_MASK) |= (intFlags & 0xFFFFU);
}

//*****************************************************************************
//
// I2C_disableInterrupt
//
//*****************************************************************************
void I2C_disableInterrupt(uint32_t base, uint32_t intFlags)
{
    //
    // Check the arguments.
    //
    ASSERT(I2C_isBaseValid(base));

    //
    // Disable the desired basic interrupts.
    //
    HWREG(base + I2C_O_INTR_MASK) &= ~(intFlags & 0xFFFFU);
}

//*****************************************************************************
//
// I2C_getInterruptStatus
//
//*****************************************************************************
uint32_t I2C_getInterruptStatus(uint32_t base)
{
    //
    // Check the arguments.
    //
    ASSERT(I2C_isBaseValid(base));

    return (HWREG(base + I2C_O_INTR_STAT));
}

//*****************************************************************************
//
// I2C_clearInterruptStatus
//
//*****************************************************************************
void I2C_clearInterruptStatus(uint32_t base, uint32_t intFlags)
{
    uint32_t tmp;

    //
    // Check the arguments.
    //
    ASSERT(I2C_isBaseValid(base));

    //
    // Clear the interrupt flags that are located in STR.
    //
    switch (intFlags)
    {
        case I2C_INT_NONE:
            break;
        case I2C_INT_RX_UNDER:
            tmp = (uint32_t)HWREG(base + I2C_O_CLR_RX_UNDER);
            break;
        case I2C_INT_RX_OVER:
            tmp = (uint32_t)HWREG(base + I2C_O_CLR_RX_OVER);
            break;
        case I2C_INT_RX_FULL:
            break;
        case I2C_INT_TX_OVER:
            tmp = (uint32_t)HWREG(base + I2C_O_CLR_TX_OVER);
            break;
        case I2C_INT_TX_EMPTY:
            break;
        case I2C_INT_RD_REQ:
            tmp = (uint32_t)HWREG(base + I2C_O_CLR_RD_REQ);
            break;
        case I2C_INT_TX_ABORT:
            tmp = (uint32_t)HWREG(base + I2C_O_CLR_TX_ABRT);
            break;
        case I2C_INT_RX_DONE:
            tmp = (uint32_t)HWREG(base + I2C_O_CLR_RX_DONE);
            break;
        case I2C_INT_ACTIVITY:
            tmp = (uint32_t)HWREG(base + I2C_O_CLR_ACTIVITY);
            break;
        case I2C_INT_STOP_CONDITION:
            tmp = (uint32_t)HWREG(base + I2C_O_CLR_STOP_DET);
            break;
        case I2C_INT_START_DET:
            tmp = (uint32_t)HWREG(base + I2C_O_CLR_START_DET);
            break;
        case I2C_INT_GEN_CALL:
            tmp = (uint32_t)HWREG(base + I2C_O_CLR_GEN_CALL);
            break;
        case I2C_INT_ALL:
            tmp = (uint32_t)HWREG(base + I2C_O_CLR_INTR);
            break;
    }
}

/***************************************************************************************************/
/* temp code of i2c lib */
void I2cPeripheralEnable(volatile struct I2C_REGS * address, enum i2cEnable_e enable)
{
    if(enable == I2CENABLE)
    {
        address->IC_ENABLE.all = address->IC_ENABLE.all | (1 << 0);
    }
    else if(enable == I2CDISABLE)
    {
        address->IC_ENABLE.all = address->IC_ENABLE.all & ~(uint32_t)(1 << 0);
    }
}

void I2cSetRole(volatile struct I2C_REGS * address, enum i2cRole_e role)
{
    if(role == I2CROLE_MASTER)
    {
        address->IC_CON.all = address->IC_CON.all | ((1 << 0) | (1 << 6));
    }
    else if(role == I2CROLE_SLAVE)
    {
        address->IC_CON.all = address->IC_CON.all & ~(uint32_t)((1 << 0) | (1 << 6));
    }
}

void I2cSetAddrBitWide(volatile struct I2C_REGS * address, enum i2cBitWide_e bitWide)
{
    address->IC_CON.all = address->IC_CON.all & ~(uint32_t)((1 << 3) | (1 << 4)) | ((bitWide << 3) | (bitWide << 4));
    address->IC_TAR.all = address->IC_TAR.all & ~(uint32_t)(1 << 12) | (bitWide << 12);
}

void I2cEnableRestart(volatile struct I2C_REGS * address, enum i2cEnable_e enable)
{
    address->IC_CON.all = address->IC_CON.all & ~(uint32_t)(1 << 5) | (enable << 5);
}

void I2CSetSelfId(volatile struct I2C_REGS * address, uint16_t id)
{
    address->IC_SAR.all = address->IC_SAR.all & ~((uint32_t)0x3FF) | (id);
}

void I2CSetDestId(volatile struct I2C_REGS * address, uint16_t id)
{
    address->IC_TAR.all = address->IC_TAR.all & ~((uint32_t)0x3FF) | (id);
}

void I2CSetBusAutoRelease(volatile struct I2C_REGS * address)
{
    address->IC_DATA_CMD.bit.STOP = 1;
}

void I2cInterruptInitial(volatile struct I2C_REGS * address)
{
    address->IC_INTR_MASK.all = 0x00;
}

void I2CEnableInterrupt(volatile struct I2C_REGS * address, enum i2cInterrupt_e interrupt, enum i2cEnable_e enable)
{
    if(enable == I2CENABLE)
    {
        address->IC_INTR_MASK.all = address->IC_INTR_MASK.all | interrupt;
    }
    else if(enable == I2CDISABLE)
    {
        address->IC_INTR_MASK.all = address->IC_INTR_MASK.all & ~(uint32_t)(interrupt);
    }
}

void I2cSendData(volatile struct I2C_REGS * address, uint8_t data)
{
    while((address->IC_STATUS.all & (1 << 1)) == 0) {};
    address->IC_DATA_CMD.all = (address->IC_DATA_CMD.all & ~((uint32_t)0x1FF)) | data;
}

void I2cReadCmd(volatile struct I2C_REGS * address)
{
    address->IC_DATA_CMD.all = address->IC_DATA_CMD.all | (uint32_t)(0x100);
}

uint8_t I2cReadData(volatile struct I2C_REGS * address)
{
    return (uint8_t)(address->IC_DATA_CMD.all & 0xFF);
}

void I2cClearIsrAllStatus(volatile struct I2C_REGS * address)
{
    uint32_t regValue = 0x00;

    regValue = address->IC_CLR_INTR;
}

uint32_t I2cGetIsrStatus(volatile struct I2C_REGS * address)
{
    return address->IC_INTR_STAT.all;
}
/***************************************************************************************************/
void i2c_control_tx_empty_signal(volatile struct I2C_REGS * address,uint8_t signal)
{
    if(!signal){
        address->IC_CON.bit.TX_EMPTY_CTRL = 0;
    }else{
        address->IC_CON.bit.TX_EMPTY_CTRL = 1;
    }
}


void i2c_generate_stop_signal(volatile struct I2C_REGS * address)
{
    address->IC_DATA_CMD.bit.STOP = 1;
}

void i2c_generate_restart_signal(volatile struct I2C_REGS * address)
{
    address->IC_DATA_CMD.bit.RESTART = 1;
}
